package com.lgl.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lgl.dto.*;
import com.lgl.entity.ResponseResult;
import com.lgl.entity.Role;
import com.lgl.entity.User;
import com.lgl.entity.UserRole;
import com.lgl.enums.AppHttpCodeEnum;
import com.lgl.exception.SystemException;
import com.lgl.mapper.UserMapper;
import com.lgl.service.RoleService;
import com.lgl.service.UserRoleService;
import com.lgl.service.UserService;
import com.lgl.utils.BeanCopyUtils;
import com.lgl.utils.SecurityUtils;
import com.lgl.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public ResponseResult getUserInfo() {
        Long userId = SecurityUtils.getUserId();
        User user = getById(userId);
        UserInfoVo userInfoVo = BeanCopyUtils.beanCopy(user, UserInfoVo.class);
        return ResponseResult.okResult(userInfoVo);


    }

    @Override
    public ResponseResult updateUserInfo(User user) {
        updateById(user);
        return ResponseResult.okResult();
    }

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public ResponseResult register(User user) {
        if (!StringUtils.hasText(user.getUserName())) {
            throw new SystemException(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getNickName())) {
            throw new SystemException(AppHttpCodeEnum.NICKNAME_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getEmail())) {
            throw new SystemException(AppHttpCodeEnum.EMAIL_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getPassword())) {
            throw new SystemException(AppHttpCodeEnum.PASSWORD_NOT_NULL);
        }
        if (userNameExist(user.getUserName())) {
            throw new SystemException(AppHttpCodeEnum.USERNAME_EXIST);
        }
        String encodePassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodePassword);
        save(user);
        return ResponseResult.okResult();

    }

    @Override
    public ResponseResult getUserList(Integer pageNum, Integer pageSize, GetUserDto getUserDto) {
//   需要用户分页列表接口。
//
//	可以根据用户名模糊搜索。
        Page<User> userPage = new Page<>();
        userPage.setCurrent(pageNum);
        userPage.setSize(pageSize);
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(getUserDto.getUserName()), User::getUserName, getUserDto.getUserName());
        queryWrapper.eq(StringUtils.hasText(getUserDto.getPhonenumber()), User::getPhonenumber, getUserDto.getPhonenumber());
        queryWrapper.eq(StringUtils.hasText(getUserDto.getStatus()), User::getStatus, getUserDto.getStatus());
        Page<User> page = page(userPage, queryWrapper);
        List<User> records = page.getRecords();
        List<UserVo> userVos = BeanCopyUtils.copyBeanList(records, UserVo.class);
        return ResponseResult.okResult(new PageVo(userVos, page.getTotal()));
//	可以进行手机号的搜索。
//
//	可以进行状态的查询。

    }

    @Override
    @Transactional
    public ResponseResult addUser(AddUserDto addUserDto) {
// 	需要新增用户功能。新增用户时可以直接关联角色。
//
//	注意：新增用户时注意密码加密存储。

//	用户名不能为空，否则提示：必需填写用户名
        if (!StringUtils.hasText(addUserDto.getUserName())) {
            throw new SystemException(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
//	用户名必须之前未存在，否则提示：用户名已存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName, addUserDto.getUserName());
        User user = getBaseMapper().selectOne(queryWrapper);
        if (!Objects.isNull(user)) {
            throw new SystemException(AppHttpCodeEnum.USERNAME_EXIST);
        }

//    手机号必须之前未存在，否则提示：手机号已存在
        LambdaQueryWrapper<User> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(User::getPhonenumber, addUserDto.getPhonenumber());
        User user2 = getBaseMapper().selectOne(queryWrapper2);
        if (!Objects.isNull(user2)) {
            throw new SystemException(AppHttpCodeEnum.PHONENUMBER_EXIST);
        }
//	邮箱必须之前未存在，否则提示：邮箱已存在
        LambdaQueryWrapper<User> queryWrapper3 = new LambdaQueryWrapper<>();
        queryWrapper3.eq(User::getEmail, addUserDto.getEmail());
        User user3 = getBaseMapper().selectOne(queryWrapper3);
        if (!Objects.isNull(user3)) {
            throw new SystemException(AppHttpCodeEnum.EMAIL_EXIST);
        }


        String encode = passwordEncoder.encode(addUserDto.getPassword());
        User userBean = BeanCopyUtils.beanCopy(addUserDto, User.class);
        userBean.setPassword(encode);
        save(userBean);
        List<Long> roleIds = addUserDto.getRoleIds();
        List<UserRole> userRoles = new ArrayList<>();
        for (Long roleId : roleIds) {
            UserRole userRole = new UserRole(userBean.getId(), roleId);
            userRoles.add(userRole);
        }
        userRoleService.saveBatch(userRoles);
        return ResponseResult.okResult();
    }

    @Override
    @Transactional
    public ResponseResult deleteUser(Long id) {
        removeById(id);
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId, id);
        userRoleService.remove(queryWrapper);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getUser(Long id) {
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId, id);
        List<UserRole> userRoleList = userRoleService.list(queryWrapper);
        List<Long> longs = new ArrayList<>();
        for (UserRole userRole : userRoleList) {
            longs.add(userRole.getRoleId());
        }
        List<Role> list = roleService.list();
        List<RolesVo> rolesVos = BeanCopyUtils.copyBeanList(list, RolesVo.class);
        User user = getById(id);
        GetUserDetailsVo getUserDetailsVo = BeanCopyUtils.beanCopy(user, GetUserDetailsVo.class);
        GetUserVo getUserVo = new GetUserVo(longs, rolesVos, getUserDetailsVo);
        return ResponseResult.okResult(getUserVo);
    }

    @Override
//    @Transactional
    public ResponseResult updateUser(UpdateUserDto updateUserDto) {
        User user = BeanCopyUtils.beanCopy(updateUserDto, User.class);
        updateById(user);
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId, updateUserDto.getId());
        userRoleService.remove(queryWrapper);
        List<UserRole> userRoles = new ArrayList<>();
        for (Long roleId : updateUserDto.getRoleIds()) {
            UserRole userRole = new UserRole(updateUserDto.getId(), roleId);
            userRoles.add(userRole);
        }
        userRoleService.saveBatch(userRoles);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult changeStatus(UserDto userDto) {
        getBaseMapper().changeStatusById(userDto);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult updatepassword(UpdatePwdDTO updatePwdDTO) {
        String yzm = stringRedisTemplate.opsForValue().get("email:code:" + updatePwdDTO.getEmail());
        if (!(StringUtils.hasText(updatePwdDTO.getYzm()) && StringUtils.hasText(yzm) && yzm.equals(updatePwdDTO.getYzm()))) {
            return ResponseResult.errorResult(500, "验证码错误");
        }
        User user = BeanCopyUtils.beanCopy(updatePwdDTO, User.class);
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getUserName, user.getUserName());
        User userFromdb = getOne(userLambdaQueryWrapper);
        if (Objects.isNull(userFromdb)){
            return ResponseResult.errorResult(500, "用户名无效");
        }
        if (!(userFromdb.getUserName().equals(updatePwdDTO.getUserName()) && userFromdb.getEmail().equals(updatePwdDTO.getEmail()))) {
            return ResponseResult.errorResult(500, "用户名或邮箱错误");
        }
        String encodePassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodePassword);
        user.setId(userFromdb.getId());
        updateById(user);
//        update(user, userLambdaQueryWrapper);
        return ResponseResult.okResult();
    }

    private boolean nickNameExist(String nickName) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getNickName, nickName);
        int count = count(queryWrapper);
        return count > 0;
    }

    private boolean userNameExist(String userName) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName, userName);
        int count = count(queryWrapper);
        return count > 0;

    }
}

